# 编译器设置
CXX := g++
CXXFLAGS := -std=c++11 -Wall -Wextra -g -pedantic
LDFLAGS := 
TARGET := ./out/program

# 源文件和头文件路径
SRC_DIR := ./src
LIB_DIR := ./lib

# 递归搜索所有源文件
MAIN_SRCS := $(wildcard $(SRC_DIR)/*.cpp $(SRC_DIR)/*.cc)
LIB_SRCS := $(shell find $(LIB_DIR) -name "*.cpp" -o -name "*.cc")
SRCS := $(MAIN_SRCS) $(LIB_SRCS)

# 生成对应的目标文件列表
OBJ_DIR := ./out/obj
DEP_DIR := ./out/dep

# 为每个源文件创建目标文件路径
OBJS := $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(notdir $(SRCS)))
OBJS := $(OBJS:.cc=.o)

# 创建源文件到目标文件的映射
SOURCE_TO_OBJ = $(addprefix $(OBJ_DIR)/,$(addsuffix .o,$(basename $(notdir $(1)))))

# 确保目录存在
$(shell mkdir -p $(OBJ_DIR) >/dev/null)
$(shell mkdir -p $(DEP_DIR) >/dev/null)

# 添加头文件包含路径（递归搜索所有包含目录）
INCLUDE_DIRS := $(shell find $(LIB_DIR) -type d)
CXXFLAGS += $(addprefix -I,$(INCLUDE_DIRS))

# 默认目标 - 构建并自动清理
all: $(TARGET)
	@echo "Build successful. Cleaning temporary files..."
	@$(MAKE) clean-temp

# 主目标链接
$(TARGET): $(OBJS)
	$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@

# 包含自动生成的依赖关系
DEPS := $(OBJS:$(OBJ_DIR)/%.o=$(DEP_DIR)/%.d)
-include $(DEPS)

# 通用规则：编译任何.cpp文件到obj目录
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
	$(CXX) $(CXXFLAGS) -MMD -MP -c $< -o $@ -MF $(DEP_DIR)/$*.d

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc
	$(CXX) $(CXXFLAGS) -MMD -MP -c $< -o $@ -MF $(DEP_DIR)/$*.d

# 查找并定义lib目录中每个源文件的规则
define COMPILE_RULE
$(OBJ_DIR)/$(notdir $(basename $(1))).o: $(1)
	$$(CXX) $$(CXXFLAGS) -MMD -MP -c $$< -o $$@ -MF $$(DEP_DIR)/$$(notdir $$(basename $$(1))).d
endef

# 为lib目录中的每个源文件创建规则
$(foreach src,$(LIB_SRCS),$(eval $(call COMPILE_RULE,$(src))))

# 清理所有生成的文件
clean:
	rm -rf $(TARGET) $(OBJ_DIR) $(DEP_DIR) *.gch *~ *.bak *.tmp
	@echo "All generated files and directories cleaned."

# 清理临时文件
clean-temp:
	# rm -f *.gch *~ *.bak *.tmp
	@echo "Temporary files cleaned."

# 重新构建
rebuild: clean all

.PHONY: all clean clean-temp rebuild
